package zzps.exeed.kernel.holder;

//import zzps.exeed.kernel.annotation.Around;
import zzps.exeed.kernel.aop.Aspect;
import zzps.exeed.kernel.core.PandaContainer;
//import zzps.exeed.kernel.core.aspect.InterceptorWorker;
//import zzps.exeed.kernel.core.aspect.Interceptor;
import zzps.exeed.kernel.tool.AnnotationTool;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.*;

public class MethodHolder {
    private Method method;
    private PandaHolder pandaHolder;
    private ParameterHolder[] parameters;
    private Class<?> returnType;
    private Type genericReturnType;
    private Annotation[] annotations;
    private List<Aspect> aspectList;
//    private List<InterceptorWorker> interceptorList = new LinkedList<>();
//    private Set<Interceptor> interceptorSet = new HashSet<>();

    public MethodHolder(PandaHolder pandaHolder,Method method) {
        method.setAccessible(true);
        this.method = method;
        this.pandaHolder = pandaHolder;
        parameters = toParameterHolder(method.getParameters());
        returnType = method.getReturnType();
        genericReturnType = method.getGenericReturnType();
        annotations = AnnotationTool.getAnnotations(method);
    }


    public ParameterHolder[] getParameters() {
        return parameters;
    }

    public Class<?> getReturnType() {
        return returnType;
    }

    public Type getGenericReturnType() {
        return genericReturnType;
    }

    public Method get() {
        return method;
    }

//    public void init(PandaContainer pandaContainer){
//        for (Annotation annotation : annotations) {
//            if (annotation instanceof Around) {
//                addAround((Around) annotation, pandaContainer);
//            } else {
//                InterceptorWorker interceptor = pandaContainer.getInterceptor(annotation.annotationType());
//                if (interceptor != null) {
//                    addAround(interceptor);
//                }
//            }
//        }
//    }
//    private void addAround(Around annotation, PandaContainer pandaContainer) {
//        PandaHolder<Interceptor> ph = pandaContainer.getOrRegister(annotation.value());
//        addAround(new InterceptorWorker(annotation.index(), ph.get()));
//    }
//    private void addAround(InterceptorWorker interceptorWorker) {
//        if(interceptorSet.contains(interceptorWorker.getReal())){
//            return;
//        }
//        interceptorSet.add(interceptorWorker.getReal());
//        interceptorList.add(interceptorWorker);
//    }
    public Object invoke(Object o, Object[] args){
        try {
            return method.invoke(o, args);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }
    private ParameterHolder[] toParameterHolder(Parameter[] parameters){
        ParameterHolder[] holders = new ParameterHolder[parameters.length];
        for (int i = 0, len = parameters.length; i < len; i++) {
            holders[i] = new ParameterHolder(parameters[i]);
        }
        return holders;
    }

    public Annotation[] annotations() {
        return annotations;
    }
    public void addAspect(Aspect aspect){
        if (aspectList == null){
            aspectList = new ArrayList<>(12);
        }
        aspectList.add(aspect);
    }

    public List<Aspect> getAspectList() {
        return aspectList;
    }
}
